﻿using UnityEngine;
using UnityEditor;
using System.IO;
using TConfig;
using Object = UnityEngine.Object;
using System;
using System.Collections;
using System.Collections.Generic;
using tcom.tools;

public class ExportAssetBundles : MonoBehaviour {

	static string resourceExtension = ".uitresource";
	static bool encodeFile = false;
	
	static void EncodeFile(string sourcePath, string newPath)
	{
		if(!encodeFile)
		{
			Debug.Log("完成打包:" + sourcePath);
			return;
		}
		
		if(File.Exists(newPath))
			File.Delete(newPath);
		
		using(FileStream sourceStream = new FileStream(sourcePath, FileMode.Open), newStream = new FileStream(newPath, FileMode.Create))
		{
			int lenght = (int)sourceStream.Length;
			byte[] assetBytes = new byte[lenght];
			sourceStream.Read(assetBytes, 0, lenght);
			
			byte[] encodeBytes = TEncodeFile.EncryptDES(assetBytes);
			newStream.Write(encodeBytes, 0, encodeBytes.Length);
		}
		
		File.Delete(sourcePath);
		Debug.Log("完成打包:" + sourcePath);
	}
	
	[MenuItem("Tools/AssetsBundles/Build Selected")]
	public static void BuildSelected()
	{
		Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
		foreach(Object obj in selection)
		{
			string path = AssetDatabase.GetAssetPath(obj);
			if(string.IsNullOrEmpty(Path.GetExtension(path)))
				continue;
			
			Debug.Log("开始打包:" + path);
			if(!path.StartsWith("Assets/GameResources/UI"))
			{
				Debug.Log(path + ":不是UI资源或者资源存放路径错误！");
				continue;
			}
			
			Object target = obj;
			if(path.StartsWith("Assets/GameResources/UI/Dep/Window"))
				target = BuildWindowWithoutResourceDependencies(path);
			
			if(target != null)
			{
				string savePath = Directory.GetCurrentDirectory() + "/data/" + path.Substring("Assets/".Length);
				savePath = Path.ChangeExtension(savePath, resourceExtension);
				string saveFileName = Path.GetFileNameWithoutExtension(savePath);
				string saveFolder = Directory.GetParent(savePath).FullName;
				
				if(!Directory.Exists(saveFolder))
					Directory.CreateDirectory(saveFolder);
				
				if(BuildPipeline.BuildAssetBundle(target, null, savePath, BuildAssetBundleOptions.CollectDependencies
					| BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.UncompressedAssetBundle,
					BuildTarget.StandaloneWindows))
				{
					string newPath = saveFolder + "/" + saveFileName + resourceExtension;
					EncodeFile(savePath, newPath);
				}
			}
			else
			{
				Debug.Log("资源打包失败:" + path);
			}
		}
	}
	
	public static void BuildFile(string path)
	{
		if(string.IsNullOrEmpty(Path.GetExtension(path)))
			return;
		
		Debug.Log("开始打包:" + path);
		if(!path.StartsWith("Assets/GameResources/UI") || Path.GetFullPath(path).Contains(".svn"))
		{
			Debug.Log(path + ":不是UI资源或者资源存放路径错误！");
			return;
		}
		
		Object target = AssetDatabase.LoadAssetAtPath(path, typeof(Object));
		if(target == null)
			return;
		
		if(path.StartsWith("Assets/GameResources/UI/Dep/Window"))
			target = BuildWindowWithoutResourceDependencies(path);
		
		if(target != null)
		{
			string savePath = Directory.GetCurrentDirectory() + "/data/" + path.Substring("Assets/".Length);
			savePath = Path.ChangeExtension(savePath, resourceExtension);
			string saveFileName = Path.GetFileNameWithoutExtension(savePath);
			string saveFolder = Directory.GetParent(savePath).FullName;
			
			if(!Directory.Exists(saveFolder))
				Directory.CreateDirectory(saveFolder);
			
			if(BuildPipeline.BuildAssetBundle(target, null, savePath, BuildAssetBundleOptions.CollectDependencies
				| BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.UncompressedAssetBundle,
				BuildTarget.StandaloneWindows))
			{
				string newPath = saveFolder + "/" + saveFileName + resourceExtension;
				EncodeFile(savePath, newPath);
			}
		}
		else
		{
			Debug.Log("资源打包失败:" + path);
		}
	}
	
	[MenuItem("Tools/AssetsBundles/Build All Resources")]
	public static void BulidResources()
	{
		BuildFonts();
		BuildMaterials();
		BuildAtlas();
		BuildEffects();
		BuildSounds();
		BuildWindows();
	}
	
	[MenuItem("Tools/AssetsBundles/Build Fonts")]
	static void BuildFonts()
	{
		BuildAllAssetBundles("Assets/GameResources/UI/Base/Font", Directory.GetCurrentDirectory() + "/data/GameResources/UI/Base/Font");
	}
	
	[MenuItem("Tools/AssetsBundles/Build Materials")]
	static void BuildMaterials()
	{
		BuildAllAssetBundles("Assets/GameResources/UI/Base/Material", Directory.GetCurrentDirectory() + "/data/GameResources/UI/Base/Material");
	}
	
	[MenuItem("Tools/AssetsBundles/Build Atlas")]
	static void BuildAtlas()
	{
		BuildAllAssetBundles("Assets/GameResources/UI/Base/Atlas", Directory.GetCurrentDirectory() + "/data/GameResources/UI/Base/Atlas");
	}
	
	[MenuItem("Tools/AssetsBundles/Build Effects")]
	static void BuildEffects()
	{
		BuildAllAssetBundles("Assets/GameResources/UI/Base/Effect", Directory.GetCurrentDirectory() + "/data/GameResources/UI/Base/Effect");
	}
	
	[MenuItem("Tools/AssetsBundles/Build Sounds")]
	static void BuildSounds()
	{
		BuildAllAssetBundles("Assets/GameResources/UI/Base/Sounds", Directory.GetCurrentDirectory() + "/data/GameResources/UI/Base/Sounds");
	}
	
	[MenuItem("Tools/AssetsBundles/Build Windows")]
	static void BuildWindows()
	{
//		BuildAllAssetBundles("Assets/GameResources/UI/Base/Sounds", Directory.GetCurrentDirectory() + "/data/GameResources/UI/Base/Sounds");
		string fileFolder = "Assets/GameResources/UI/Dep/Window";
		string saveFolder = Directory.GetCurrentDirectory() + "Assets/GameResources/UI/Dep/Window";
		string rootPath = Directory.GetCurrentDirectory() + "/data/";
		
		char[] separatorCharArray = {'/', '\\'};
		fileFolder = fileFolder.TrimEnd(separatorCharArray);
		saveFolder = saveFolder.TrimEnd(separatorCharArray);
		
		string[] files = Directory.GetFiles(fileFolder, "*", SearchOption.AllDirectories);
		foreach(string file in files)
		{
			if(Path.GetExtension(file) == ".meat" || Path.GetFullPath(file).Contains(".svn"))
				continue;
			
			Debug.Log("开始打包:" + file);
			
			Object obj = BuildWindowWithoutResourceDependencies(file);
			if(obj != null)
			{
				string saveFileDirectory = saveFolder + Path.GetDirectoryName(file).Substring(fileFolder.Length);
				string saveFileName = Path.GetFileNameWithoutExtension(file);
				string saveFileExtension = resourceExtension;
				string saveFilePath = Path.Combine(saveFileDirectory, saveFileName + saveFileExtension);
				
				if(!Directory.Exists(saveFileDirectory))
					Directory.CreateDirectory(saveFileDirectory);
				
				try
				{
					if(BuildPipeline.BuildAssetBundle(obj, null, saveFilePath, BuildAssetBundleOptions.CollectDependencies
					| BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.UncompressedAssetBundle,
						BuildTarget.StandaloneWindows))
					{
						string newPath = saveFileDirectory + "/" + saveFileName + saveFileExtension;
						EncodeFile(saveFilePath, newPath);
					}
				}
				catch(Exception e)
				{
					Debug.Log(e);
					Debug.LogException(e);
				}
				
			}
			else
			{
				Debug.Log("资源打包失败:" + file);
			}
		}
	}
	
	/// <summary>
	///  移除UI资源引用并保存到临时文件夹
	/// </param>
	static Object BuildWindowWithoutResourceDependencies(string file)
	{
		Object obj = AssetDatabase.LoadMainAssetAtPath(file);
		if(obj == null)
			return null;
		
		string localPath = AssetDatabase.GetAssetPath(obj);
		string[] str = localPath.Split('/');
		string saveRelativePath = localPath.Substring(str[0].Length + str[1].Length + 2);
		string savePath = "Assets/TempResources/" + saveRelativePath;
		string savePathFolder = Directory.GetParent(savePath).FullName;
		
		if(!Directory.Exists(savePathFolder))
			Directory.CreateDirectory(savePathFolder);
		
		if(File.Exists(savePath))
		{
			File.Delete(savePath);
			AssetDatabase.Refresh();
		}
		
		AssetDatabase.CopyAsset(localPath, savePath);
		AssetDatabase.Refresh();
		
		GameObject go = AssetDatabase.LoadMainAssetAtPath(savePath) as GameObject;
		List<UIWidget> widgets = NGUITools.FindInChildren<UIWidget>(go);
		foreach(UIWidget widget in widgets)
		{
			widget.mustLoad = true;
			widget.isUnload = true;
			widget.UpdateSrcPath(true);
			widget.packaging = true;
			
			if(widget is UILabel)
			{
				UILabel label = widget as UILabel;
				label.font = null;
			}
			else if(widget is UISprite)
			{
				UISprite sprite = widget as UISprite;
				sprite.atlas = null;
			}
			else if(widget is UITexture)
			{
				UITexture texture = widget as UITexture;
				texture.material = null;
			}
			
			if(widget.material != null)
				widget.material = null;
			
			if(widget.material != null)
			{
				Debug.LogError(widget.material);
				Debug.LogError(widget.name, widget);
				widget.material = null;
			}
			
			widget.isUnload = false;
			widget.packaging = false;
		}
		
//		List<UIMix> mixs = NGUITools.FindInChildren<UIMix>(go);
//		foreach(UIMix mix in mixs)
//		{
//			mix.UpdateSrcPath(false);
//			mix.packaging = true;
//			mix.defaultAtlas = null;
//			mix.defaultFont = null;
//			mix.fontList.Clear();
//			mix.atlasList.Clear();
//		}
		
		List<UIPopupList> popList = NGUITools.FindInChildren<UIPopupList>(go);
		foreach(UIPopupList pop in popList)
		{
			pop.UpdateSrcPath(false);
			pop.packaging = true;
			pop.font = null;
			pop.atlas = null;
		}
		
		List<UIButtonSound> bSounds = NGUITools.FindInChildren<UIButtonSound>(go);
		foreach(UIButtonSound bSound in bSounds)
		{
			bSound.UpdateSrcPath(false);
			bSound.packaging = true;
			bSound.audioClip = null;
		}
		
//		List<UI3D> u3dList = NGUITools.FindInChildren<UI3D>(go);
//		foreach(UI3D u3d in u3dList)
//		{
//			u3d.mustLoad = true;
//			u3d.isUnload = true;
//			u3d.UpdateSrcPath(false);
//			u3d.packaging = true;
//			if(!string.IsNullOrEmpty(u3d.srcPath) && u3d.target != null)
//			{
//				DestroyImmediate(u3d.target, true);
//			}
//			u3d.prefab = null;
//			u3d.isUnload = false;
//		}
//		
//		List<UIMaterial> matList = NGUITools.FindInChildren<UIMaterial>(go);
//		foreach(UIMaterial mat in matList)
//		{
//			mat.mustLoad = true;
//			mat.isUnload = true;
//			mat.UpdateSrcPath(false);
//			mat.packaging = true;
//			mat.material = null;
//			mat.isUnload = false;
//			mat.packaging = false;
//		}
		
		EditorUtility.SetDirty(go);
		AssetDatabase.Refresh();
		return go;
	}
	
	static void BuildAllAssetBundles(string fileFolder, string saveFolder)
	{
		string root = Directory.GetCurrentDirectory() + "/data/";
		char[] separatorCharArray = {'/', '\\'};
		
		fileFolder = fileFolder.TrimEnd(separatorCharArray);
		saveFolder = saveFolder.TrimEnd(separatorCharArray);
		string[] files = Directory.GetFiles(fileFolder, "*", SearchOption.AllDirectories);
		foreach(string file in files)
		{
			if(Path.GetExtension(file) == ".meat" || Path.GetFullPath(file).Contains(".svn"))
				continue;
			
			Debug.Log("开始打包:" + file);
			
			Object obj = AssetDatabase.LoadMainAssetAtPath(file);
			
			if(obj != null)
			{
				string saveFileDirectory = saveFolder + Path.GetDirectoryName(file).Substring(fileFolder.Length);
				string saveFileName = Path.GetFileNameWithoutExtension(file);
				string saveFileExtension = resourceExtension;
				string saveFilePath = Path.Combine(saveFileDirectory, saveFileName + saveFileExtension);
				
				if(!Directory.Exists(saveFileDirectory))
					Directory.CreateDirectory(saveFileDirectory);
				
				try
				{
					if(BuildPipeline.BuildAssetBundle(obj, null, saveFilePath, BuildAssetBundleOptions.CollectDependencies
					| BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.UncompressedAssetBundle,
						BuildTarget.StandaloneWindows))
					{
						string newPath = saveFileDirectory + "/" + saveFileName + saveFileExtension;
						EncodeFile(saveFilePath, newPath);
					}
				}
				catch(Exception e)
				{
					Debug.Log(e);
					Debug.LogException(e);
				}
				
			}
			else
			{
				Debug.Log("不可识别的资源:" + file);
			}
		}
	}
	
	[MenuItem("Tools/AssetsBundles/Just Build Selected")]
	public static void JustBuildSelected()
	{
		Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
		foreach(Object obj in selection)
		{
			string path = AssetDatabase.GetAssetPath(obj);
			if(string.IsNullOrEmpty(Path.GetExtension(path)))
				continue;
			
			Debug.Log("开始打包:" + path);
			
			Object target = obj;
			if(target != null)
			{
				string savePath = Directory.GetCurrentDirectory() + "/data/" + path.Substring("Assets/".Length);
				savePath = Path.ChangeExtension(savePath, resourceExtension);
				string saveFileName = Path.GetFileNameWithoutExtension(savePath);
				string saveFolder = Directory.GetParent(savePath).FullName;
				
				if(!Directory.Exists(saveFolder))
					Directory.CreateDirectory(saveFolder);
				
				if(BuildPipeline.BuildAssetBundle(target, null, savePath, BuildAssetBundleOptions.CollectDependencies
					| BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.UncompressedAssetBundle,
					BuildTarget.StandaloneWindows))
				{
					string newPath = saveFolder + "/" + saveFileName + resourceExtension;
					EncodeFile(savePath, newPath);
				}
			}
			else
			{
				Debug.Log("资源打包失败:" + path);
			}
		}
	}
	
	static void BuildOneAssetBundles(string filePath, string saveFilePath)
	{
		string root = Directory.GetCurrentDirectory() + "/data/";
		Object obj = AssetDatabase.LoadMainAssetAtPath(filePath);
		if(obj != null)
		{
			string saveFileDirectory = Path.GetDirectoryName(saveFilePath);
			string saveFileName = Path.GetFileNameWithoutExtension(saveFilePath);
			
			if(!Directory.Exists(saveFileDirectory))
				Directory.CreateDirectory(saveFileDirectory);
			
			if(BuildPipeline.BuildAssetBundle(obj, null, saveFilePath, BuildAssetBundleOptions.CollectDependencies
					| BuildAssetBundleOptions.CompleteAssets | BuildAssetBundleOptions.UncompressedAssetBundle,
					BuildTarget.StandaloneWindows))
			{
				string newPath = saveFileDirectory + "/" + saveFileName + resourceExtension;
				EncodeFile(saveFilePath, newPath);
			}
		}
	}
	
	#region //Export Configs
	
	#region //Export Windows Configs
	
	static bool ISUIEditorScene()
	{
		if(EditorApplication.currentScene != "Asset/UIEditro.unity")
		{
			bool open = EditorUtility.DisplayDialog("Scene error", "Please open the UIEditor scene first!",
				"Open Now(And save current scene)", "Lates");
			if(!open)
				return false;
			else
			{
				if(EditorApplication.SaveCurrentSceneIfUserWantsTo())
					EditorApplication.SaveScene();
				
				EditorApplication.OpenScene("Asset/UIEditro.unity");
			}
		}
		return true;
	}
	
	[MenuItem("Tools/Window/Save configs")]
	public static void ExportWindowInfos()
	{
		string rootPath = Directory.GetCurrentDirectory() + "/Assets/GameResources/UI/Dep/Window/";
		string[] files = Directory.GetFiles(rootPath);
		Transform cameraTrans = (FindSceneObjectsOfType(typeof(UICamera)) as UICamera[])[0].transform;
		
		List<GameObject> list = new List<GameObject>();
		foreach(string file in files)
		{
			if(!Path.GetFileNameWithoutExtension(file).Contains("Window") || file.Contains(".meta"))
				continue;
			
			string localPath = file.Substring(Directory.GetCurrentDirectory().Length + 1);
			Object obj = AssetDatabase.LoadMainAssetAtPath(localPath);
			
			GameObject windowObj = Instantiate(obj) as GameObject;
			windowObj.name = windowObj.name.TrimEnd("(Clone)".ToCharArray());
			Transform windowTrans = windowObj.transform;
			windowTrans.parent = cameraTrans;
			windowTrans.localPosition = Vector3.zero;
			windowTrans.localRotation = Quaternion.identity;
			windowTrans.localScale = Vector3.one;
			
			Window window = windowObj.GetComponent<Window>();
			if(window == null)
			{
				DestroyImmediate(windowObj);
				continue;
			}
			
			window.HideDefaultHideChildren();
			list.Add(windowObj);
		}
		
		string folderPath = Directory.GetParent(Application.dataPath).FullName + "/data/GameResources/UI/Configs/";
		if(!Directory.Exists(folderPath))
			Directory.CreateDirectory(folderPath);
		
		try{
			WindowDB windowDB = new WindowDB();
			for(int i = 0; i < list.Count; i++)
			{
				GameObject go = list[i];
				windowDB.SaveNodes(go.transform);
				string savePath = folderPath + go.name + ".xml";
				XML<WindowDB>.SaveAtPath(windowDB, savePath);
			}
		}
		catch(Exception e){
			Debug.Log(e);
			Debug.LogException(e);
		}
		
		for(int i = 0; i < list.Count; i++)
		{
			DestroyImmediate(list[i]);
		}
	}
	
	[MenuItem("Tools/Window/Save current configs")]
	public static void ExportCurrentWindowInfo()
	{
		GameObject windowObj = Selection.activeGameObject;
		Transform windowTrans = windowObj.transform;
		Window window = windowObj.GetComponent<Window>();
		if(window == null)
			return;
		
		string folderPath = Directory.GetParent(Application.dataPath).FullName + "/data/GameResources/UI/Configs/";
		if(!Directory.Exists(folderPath))
			Directory.CreateDirectory(folderPath);
		try{
			WindowDB windowDB = new WindowDB();
			windowDB.SaveNodes(windowTrans);
			string savePath = folderPath + windowObj.name + ".xml";
			XML<WindowDB>.SaveAtPath(windowDB, savePath);
		}
		catch(Exception e){
			Debug.Log(e);
			Debug.LogException(e);
		}
	}
	
	#endregion //Export Windows Configs
	
	#endregion //Export Configs
	
	[MenuItem("Tools/File/Extension to .uitresource")]
	public static void ChangeExtion()
	{
		string fileFolder = Directory.GetParent(Application.dataPath) + "/data/GameResources/UI/";
		string[] files = Directory.GetFiles(fileFolder, "*.tresource", SearchOption.AllDirectories);
		foreach(string file in files)
		{
			string movePath = Path.ChangeExtension(file, ".uitresource");
			File.Move(file, movePath);
		}
	}
}
